From 1259a489f2a6b07d6d406eea8c1c8e86634ecb73 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Mon, 7 Nov 2016 18:25:12 +0100 Subject: [PATCH] iconhelper: Add support for GskTexture ... and use that in GtkImage. --- gtk/gtkiconhelper.c | 55 ++++++++++++++++++++++++++++++++++++++ gtk/gtkiconhelperprivate.h | 2 ++ gtk/gtkimage.c | 42 ++++++++++++++--------------- 3 files changed, 78 insertions(+), 21 deletions(-) diff --git a/gtk/gtkiconhelper.c b/gtk/gtkiconhelper.c index 1d196d4c92..278ace34ff 100644 --- a/gtk/gtkiconhelper.c +++ b/gtk/gtkiconhelper.c @@ -43,6 +43,7 @@ struct _GtkIconHelperPrivate { guint rendered_surface_is_symbolic : 1; cairo_surface_t *rendered_surface; + GskTexture *texture; }; G_DEFINE_TYPE_WITH_PRIVATE (GtkIconHelper, gtk_icon_helper, GTK_TYPE_CSS_GADGET) @@ -50,6 +51,8 @@ G_DEFINE_TYPE_WITH_PRIVATE (GtkIconHelper, gtk_icon_helper, GTK_TYPE_CSS_GADGET) static void gtk_icon_helper_invalidate (GtkIconHelper *self) { + g_clear_pointer (&self->priv->texture, gsk_texture_unref); + if (self->priv->rendered_surface != NULL) { cairo_surface_destroy (self->priv->rendered_surface); @@ -95,6 +98,7 @@ gtk_icon_helper_take_definition (GtkIconHelper *self, void _gtk_icon_helper_clear (GtkIconHelper *self) { + g_clear_pointer (&self->priv->texture, gsk_texture_unref); g_clear_pointer (&self->priv->rendered_surface, cairo_surface_destroy); gtk_image_definition_unref (self->priv->def); @@ -554,6 +558,34 @@ gtk_icon_helper_ensure_surface (GtkIconHelper *self) self->priv->rendered_surface = gtk_icon_helper_load_surface (self, scale); } +static void +gtk_icon_helper_ensure_texture (GtkIconHelper *self, + GskRenderer *renderer) +{ + cairo_surface_t *map; + int width, height, scale; + + if (self->priv->texture) + return; + + gtk_icon_helper_ensure_surface (self); + if (self->priv->rendered_surface == NULL) + return; + + scale = gtk_widget_get_scale_factor (gtk_css_gadget_get_owner (GTK_CSS_GADGET (self))), + _gtk_icon_helper_get_size (self, &width, &height); + map = cairo_surface_map_to_image (self->priv->rendered_surface, + &(GdkRectangle) { 0, 0, width * scale, height * scale}); + + self->priv->texture = gsk_texture_new_for_data (renderer, + cairo_image_surface_get_data (map), + width * scale, + height * scale, + cairo_image_surface_get_stride (map)); + + cairo_surface_unmap_image (self->priv->rendered_surface, map); +} + void _gtk_icon_helper_get_size (GtkIconHelper *self, gint *width_out, @@ -825,6 +857,29 @@ _gtk_icon_helper_draw (GtkIconHelper *self, } } +GskRenderNode * +gtk_icon_helper_get_render_node (GtkIconHelper *self, + GskRenderer *renderer) +{ + GskTexture *texture; + GskRenderNode *node; + graphene_rect_t bounds; + + gtk_icon_helper_ensure_texture (self, renderer); + texture = self->priv->texture; + if (texture == NULL) + return NULL; + + graphene_rect_init (&bounds, 0, 0, gsk_texture_get_width (texture), gsk_texture_get_height (texture)); + + node = gsk_renderer_create_render_node (renderer); + gsk_render_node_set_name (node, "Icon Helper"); + gsk_render_node_set_bounds (node, &bounds); + gsk_render_node_set_texture (node, texture); + + return node; +} + gboolean _gtk_icon_helper_get_is_empty (GtkIconHelper *self) { diff --git a/gtk/gtkiconhelperprivate.h b/gtk/gtkiconhelperprivate.h index 849aeb12a6..6576e81519 100644 --- a/gtk/gtkiconhelperprivate.h +++ b/gtk/gtkiconhelperprivate.h @@ -125,6 +125,8 @@ void _gtk_icon_helper_draw (GtkIconHelper *self, cairo_t *cr, gdouble x, gdouble y); +GskRenderNode * gtk_icon_helper_get_render_node (GtkIconHelper *self, + GskRenderer *renderer); gboolean _gtk_icon_helper_get_force_scale_pixbuf (GtkIconHelper *self); void _gtk_icon_helper_set_force_scale_pixbuf (GtkIconHelper *self, diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c index ae8dec8c5e..7d5e99f92f 100644 --- a/gtk/gtkimage.c +++ b/gtk/gtkimage.c @@ -1420,44 +1420,44 @@ gtk_image_get_render_node (GtkWidget *widget, if (res == NULL) return NULL; - node = gtk_widget_create_render_node (widget, renderer, "Image Content"); + if (gtk_image_get_storage_type (image) == GTK_IMAGE_ANIMATION) + { + node = gtk_widget_create_render_node (widget, renderer, "Image Content"); - gtk_widget_get_clip (widget, &clip); - _gtk_widget_get_allocation (widget, &alloc); + gtk_widget_get_clip (widget, &clip); + _gtk_widget_get_allocation (widget, &alloc); - cr = gsk_render_node_get_draw_context (node, renderer); - cairo_translate (cr, alloc.x - clip.x, alloc.y - clip.y); - x = 0; - y = 0; - width = alloc.width; - height = alloc.height; + cr = gsk_render_node_get_draw_context (node, renderer); + cairo_translate (cr, alloc.x - clip.x, alloc.y - clip.y); + x = 0; + y = 0; + width = alloc.width; + height = alloc.height; - _gtk_icon_helper_get_size (priv->icon_helper, &w, &h); + _gtk_icon_helper_get_size (priv->icon_helper, &w, &h); - baseline = gtk_widget_get_allocated_baseline (widget); + baseline = gtk_widget_get_allocated_baseline (widget); - if (baseline == -1) - y += floor(height - h) / 2; - else - y += CLAMP (baseline - h * gtk_image_get_baseline_align (image), 0, height - h); + if (baseline == -1) + y += floor(height - h) / 2; + else + y += CLAMP (baseline - h * gtk_image_get_baseline_align (image), 0, height - h); - x += (width - w) / 2; + x += (width - w) / 2; - if (gtk_image_get_storage_type (image) == GTK_IMAGE_ANIMATION) - { GtkStyleContext *context = gtk_widget_get_style_context (widget); GdkPixbuf *pixbuf = get_animation_frame (image); gtk_render_icon (context, cr, pixbuf, x, y); g_object_unref (pixbuf); + + cairo_destroy (cr); } else { - _gtk_icon_helper_draw (priv->icon_helper, cr, x, y); + node = gtk_icon_helper_get_render_node (priv->icon_helper, renderer); } - cairo_destroy (cr); - gsk_render_node_append_child (res, node); gsk_render_node_unref (node); -- 2.30.2